using System;
using System.Collections;

namespace RomanJendrusz.Amazon.ETL.Infrastructure.IoC
{
    /// <summary>
    /// Represents the gateway to an iversion of control container
    /// </summary>
    public class IoCGateway
    {
        private static IDependencyResolver _resolver;
        private static readonly object _sync = new object();

        /// <summary>
        /// Resolves the specified type of object
        /// </summary>
        /// <typeparam name="Dependency">The type of the dependency.</typeparam>
        /// <returns></returns>
        public static Dependency Resolve<Dependency>()
        {
            EnsureResolver();
            return _resolver.Resolve<Dependency>();
        }

        private static void EnsureResolver()
        {
            if(_resolver == null)
            {
                throw new InvalidOperationException("The inversion of control gateway was not configured");
            }
        }

        /// <summary>
        /// Resolves the specified type of object with key.
        /// </summary>
        /// <typeparam name="Dependency">The type of the dependency.</typeparam>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        public static Dependency Resolve<Dependency>(string key)
        {
            EnsureResolver();
            return _resolver.Resolve<Dependency>(key);
        }

        public static Object Resolve(Type service)
        {
            EnsureResolver();
            return _resolver.Resolve(service);
        }

        /// <summary>
        /// Resolves the specified type of object with arguments.
        /// </summary>
        /// <typeparam name="Dependency">The type of the dependency.</typeparam>
        /// <param name="arguments">The arguments.</param>
        /// <returns></returns>
        public static Dependency Resolve<Dependency>(IDictionary arguments)
        {
            EnsureResolver();
            return _resolver.Resolve<Dependency>(arguments);
        }

        /// <summary>
        /// Adds the instance.
        /// </summary>
        /// <typeparam name="Type">The type of the instance.</typeparam>
        /// <param name="injectedInstance">The injected instance.</param>
        public static  void AddInstance<Type>(Type injectedInstance)
        {
            EnsureResolver();
            _resolver.AddInstance<Type>(injectedInstance);
        }
        /// <summary>
        /// Initializes the gateway with specified resolver.
        /// </summary>
        /// <param name="resolver">The resolver.</param>
        public static void Initialize(IDependencyResolver resolver)
        {
            if (resolver == null) throw new ArgumentNullException("resolver");
            lock (_sync)
            {
                _resolver = resolver;
            }
        }
    }
}